前面我們手刻了一支登入測試,一行一行寫 page.goto、page.fill、page.click。除了自己手寫這些測試程式碼外,Playwright 其實有內建的 Codegen 工具,可以錄製並自動生成測試程式碼,今天就來實際操作看看吧!
Codegen 是 Playwright 內建的錄製工具,它會啟動一個瀏覽器,我們在上面操作畫面、打字等等,它會在背景把你的操作即時轉成程式碼。這樣我們不需要自己記 API、不用自己選 locator 就可以完成測資的操作流程,對第一次寫 E2E 測試的人來說,門檻降低很多。
啟動 Codegen 的方式很簡單:
npx playwright codegen http://localhost:8000/
執行後會跳出兩個視窗:一個是實際操作用的瀏覽器,另一個是 Playwright Inspector,當在瀏覽器上操作的時候,右側會即時顯示對應的程式碼。你在瀏覽器裡做的每個動作(點擊、輸入、選取下拉選單),都會馬上被翻譯成一行程式碼出現在 Inspector 裡。
我們試試在同樣的登入場景(帳號、密碼、送出)使用 Codegen 錄製,點下錄製鈕後就可以操作瀏覽器了,整個過程你只要像平常手動操作網站一樣點擊輸入即可,旁邊打開的視窗會記錄你做了哪些操作,操作結束再按下結束錄製就完成了,之後可以把產出的code存起來。

產出的程式碼大致長這樣:
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:8000/#/login');
await page.getByRole('textbox', { name: 'Username' }).click();
await page.getByRole('textbox', { name: 'Username' }).fill('demo');
await page.getByRole('textbox', { name: 'Username' }).press('Tab');
await page.getByRole('textbox', { name: 'Password' }).press('Unidentified');
await page.getByRole('textbox', { name: 'Password' }).fill('demo');
await page.getByRole('button', { name: 'Sign in' }).click();
});
把錄製的程式碼跟我們之前寫的驗證登入功能的test比較,可以發現有些不同,雖然目前我們還沒有開始實作test case,但一般來說錄製的跟我們自己撰寫的測試程式會有下面這些差別:
多餘的操作步驟:Codegen 會記錄你每一個滑鼠動作,像上面 click() 完再 fill(),但其實直接 fill 就好,因為 Playwright 的 fill 本身就會先點擊再輸入。
缺乏結構與意圖:Codegen 產出的是一份操作流程,他不會去考量哪些程式碼可以封裝後復用,只是單純把你的操作列出來,但如果我們自己撰寫測試可以知道有哪些操作常常出現,這時我們就會把常用的操作包裝成函式方便復用。另外錄製的程式碼也看不太出來這個操作具體是要驗證什麼功能或是預期結果,比較沒有辦法從中理解程式碼的意圖。
斷言要自己補:Codegen 只負責記錄操作,不會知道你想驗證什麼結果,所以登入成功後應該出現的畫面、應該導向的頁面,這些斷言都得自己手動加上去。
選取元素的方式:目前我們看到的都是使用getByRole、getByLabel 這類語意化 locator去選取畫面上的元素操作。如果畫面上沒有明確的 label 或 role等元素,就必須靠文字內容或是其他css selector屬性去抓取,這種抓取方式的穩定度比較脆弱,但是Codegen比較不會去考量這些。當碰到這種情況,比較推薦的做法是在目標網頁上增加自定義的屬性(像是 data-testid),讓抓取元素不需要依賴特定的css selector數值,這樣即使css有調整也不需要調整測試內容。
Codegen 很適合用來快速產出一個簡單的測試操作骨架,但還是要經過人工修改才能變成一份真正好維護的測試,包括調整 locator 的穩定度、補上斷言、拆解成有意圖的結構等,具體每個測試的目的還是需要我們自己想清楚才行。
接下來我們會學習一直提到的locator,然後一步一步優化目前手寫跟録製的程式碼。